#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <boost/filesystem.hpp>
#include <unistd.h>
#include <filesystem>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
#include "Log.hpp"
namespace util
{
    using namespace ns_log;
    class FileTool
    {
    public:
        // 写入文件
        static bool Write(const std::string &filepath, const std::string &buf)
        {
            std::ofstream ofs(filepath, std::ios::app);
            if (!ofs.is_open())
            {
                LOG(ERROR, "写入文件失败,文件路径: %s,可能是权限不足或者目录不存在\n", filepath.c_str());
                return false;
            }
            ofs << buf;
            if (!ofs.good())
            {
                LOG(ERROR, "写入文件失败\n");
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }
        // 读取文件
        static bool Read(const std::string &filepath, std::string *out)
        {
            std::ifstream ifs(filepath);
            if (!ifs.is_open())
            {
                LOG(ERROR, "读取文件失败,文件路径: %s,可能是权限不足或者文件不存在\n", filepath.c_str());
                return false;
            }
            int size = FileSize(filepath);
            out->resize(size);
            ifs.read(&((*out)[0]), size);
            if (!ifs.good())
            {
                LOG(ERROR, "读取文件的过程出现错误,可能是缓冲区不足\n");
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }
        // 判断一个目录/文件是否有效
        static bool IsExists(const std::string &filepath)
        {
            int n = access(filepath.c_str(), F_OK);
            if (n < 0)
            {
                LOG(DEBUG, "%s不存在\n", filepath.c_str());
                return false;
            }
            return true;
        }
        // 判断是否是普通文件
        static bool IsNormalFile(const std::string &filepath)
        {
            if (!IsExists(filepath))
                return false;
            struct stat filestatu;
            if (stat(filepath.c_str(), &filestatu) == -1)
            {
                LOG(ERROR, "获取文件属性失败,错误信息:%s\n", strerror(errno));
                return false;
            }
            return S_ISREG(filestatu.st_mode);
        }
        // 遍历指定路径下的所有指定后缀名的文件名
        static bool GetAllFilesWithExtensionInPath(const std::string &path, std::vector<std::string> *res,
                                                   const std::string &suffix)
        {
            namespace fs = boost::filesystem;
            // 定义目录path对象
            fs::path root(path);
            if (!fs::exists(root))
            {
                LOG(ERROR, "用户指定的%s路径是无效的!\n", path.c_str());
                return false;
            }
            // 递归遍历root下的所有子文件
            fs::recursive_directory_iterator end;
            for (fs::recursive_directory_iterator iter(root); iter != end; iter++)
            {
                if (!fs::is_regular_file(*iter))
                {
                    continue;
                }
                // 筛选后缀
                if (iter->path().extension() != suffix)
                {
                    continue;
                }
                res->push_back(iter->path().string());
            }
           return true;
        }
        // 获取指定文件大小
        static size_t FileSize(const std::string &filepath)
        {
            if (!IsExists(filepath))
                return -1;
            struct stat filestatu;
            if (stat(filepath.c_str(), &filestatu) == -1)
            {
                LOG(ERROR, "获取文件属性失败,错误信息:%s\n", strerror(errno));
                return -1;
            }
            return filestatu.st_size;
        }
        // 删除指定路径下的文件
        static void Remove(const std::string &filepath)
        {
            if (!IsExists(filepath))
                return;
            remove(filepath.c_str());
        }
        // 修改指定路径下文件的权限
        static bool ChangeFileMode(const std::string &filepath, int flag)
        {
            if (!IsExists(filepath))
                return false;
            return chmod(filepath.c_str(), flag) == 0 ? true : false;
        }
        // 在指定路径下创建目录
        static bool CreateDir(const std::string &dirname)
        {
            if (IsExists(dirname))
            {
                LOG(INFO, "目录已存在,无需创建,%s\n", dirname.c_str());
                return false;
            }
            int n = mkdir(dirname.c_str(), 0777);
            if (n < 0)
            {
                LOG(ERROR, "创建目录:%s失败,错误信息: %s\n", dirname.c_str(), strerror(errno));
                return false;
            }
            return true;
        }
    };
}